#ifndef __MATCHING_HPP__
#define __MATCHING_HPP__
#include "dp.hpp"
#include "conn_ctl.hpp"
#include "room.hpp"
#include <condition_variable>
#include <list>
// 匹配队列
template <class T>
class match_list
{
private:
    std::list<T> _list;
    std::mutex _mutex;
    std::condition_variable _cond;

public:
    match_list() {}
    ~match_list() {}

    // 返回队列元素个数
    int size()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        return _list.size();
    }

    // 查看队列是否为空
    bool empty()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        return _list.empty();
    }

    // 休眠线程
    void wait()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _cond.wait(lock);
    }

    // 入队列
    void push(const T &value)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _list.push_back(value);

        // 唤醒线程
        _cond.notify_all();
    }

    // 出队列并且拿到元素
    bool pop(T &value)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        if (_list.empty())
        {
            return false;
        }
        value = _list.front();
        _list.pop_front();
        return true;
    }

    // 从队列中删除指定元素
    void remove(const T &value)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _list.remove(value);
    }
};

class match_ctl
{
private:
    match_list<int> _low_list; // 0 - 1500(不包括1500) 分的匹配队列
    match_list<int> _mid_list; // 1500 - 2000(不包括2000)
    match_list<int> _hig_list; // 2000 以上
    user_table *_table;
    room_ctl *_room_ctl;
    conn_ctl *_conn_ctl;

    std::thread _low_hdl; // 分别对应处理三个匹配队列的线程
    std::thread _mid_hdl;
    std::thread _hig_hdl;

    void _low_func() { _real_func(&_low_list); } // 分别对应三个线程的执行函数
    void _mid_func() { _real_func(&_mid_list); }
    void _hig_func() { _real_func(&_hig_list); }

    void _real_func(match_list<int> *lt) // 线程执行的函数
    {
        while (1)
        {
            while (lt->size() < 2) // 用户不够则阻塞
            {
                debug_log("线程阻塞 %d",lt->size());
                lt->wait();
            }
            //唤醒线程后提示一下
            debug_log("线程唤醒: %d",lt->size());
            // 取出来
            int user1, user2;
            bool ret = lt->pop(user1);
            if (!ret)
            {
                continue;
            }

            ret = lt->pop(user2);
            if (!ret)
            {
                add(user1);
                continue;
            }

            // 判断是否在大厅中
            server::connection_ptr ptr1 = _conn_ctl->get_con_square(user1);
            if (ptr1.get() == nullptr)
            {
                add(user2);
                continue;
            }
            server::connection_ptr ptr2 = _conn_ctl->get_con_square(user2);
            if (ptr2.get() == nullptr)
            {
                add(user1);
                continue;
            }

            // 用户在线，创建 room 添加用户
            room_ptr roomptr = _room_ctl->create_room(user1, user2);
            if (roomptr.get() == nullptr)
            {
                add(user1);
                add(user2);
                error_log("房间创建失败");
                continue;
            }

            // 对用户返回结果
            Json::Value root;
            std::string str;
            root["optype"] = "match_success";
            root["result"] = true;
            json_util::serialize(root, str);
            ptr1->send(str);
            ptr2->send(str);
        }
    }

public:
    match_ctl(user_table *table, room_ctl *roomctl, conn_ctl *connctl) : _table(table), _room_ctl(roomctl), _conn_ctl(connctl),
                                                                         _low_hdl(std::thread(&match_ctl::_low_func, this)),
                                                                         _mid_hdl(std::thread(&match_ctl::_mid_func, this)),
                                                                         _hig_hdl(std::thread(&match_ctl::_hig_func, this))
    {
    }
    ~match_ctl() {}

    bool add(int id) // 添加用户到匹配队列
    {
        // 先从用户管理列表拿到分数
        Json::Value root;
        if (!_table->select_by_id(id, root))
        {
            debug_log("用户数据获取失败");
            return false;
        }
        int score = root["score"].asInt();

        // 判断分数
        if (score < 1500)
        {
            _low_list.push(id);
        }
        else if (score >= 1500 && score < 2000)
        {
            _mid_list.push(id);
        }
        else
        {
            _hig_list.push(id);
        }

        return true;
    }

    bool del(int id) // 删除用户从匹配队列
    {
        // 先从用户管理列表拿到分数
        Json::Value root;
        if (!_table->select_by_id(id, root))
        {
            debug_log("用户数据获取失败");
        }
        int score = root["score"].asInt();

        // 判断分数
        if (score < 1500)
        {
            _low_list.remove(id);
        }
        else if (score >= 1500 && score < 2000)
        {
            _mid_list.remove(id);
        }
        else
        {
            _hig_list.remove(id);
        }

        return true;
    }
};
#endif